home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Information / Languages / C++ / C++ FAQ 3⁄4 < prev    next >
Encoding:
Internet Message Format  |  1994-12-08  |  33.1 KB  |  [TEXT/R*ch]

  1. Path: bloom-beacon.mit.edu!gatech!howland.reston.ans.net!pipex!uunet!library.erc.clarkson.edu!sun.soe.clarkson.edu!cline
  2. From: cline@sun.soe.clarkson.edu (Marshall Cline)
  3. Newsgroups: comp.lang.c++
  4. Subject: C++ FAQ: posting #3/4
  5. Followup-To: comp.lang.c++
  6. Date: 14 Nov 1994 00:26:37 GMT
  7. Organization: Paradigm Shift, Inc (training/consulting/OOD/OOP/C++)
  8. Lines: 639
  9. Sender: cline@sun.soe.clarkson.edu
  10. Distribution: world
  11. Expires: +1 month
  12. Message-ID: <3a6art$gd8@library.erc.clarkson.edu>
  13. Reply-To: cline@parashift.com (Marshall Cline)
  14. NNTP-Posting-Host: sun.soe.clarkson.edu
  15. Summary: Please read this before posting to comp.lang.c++
  16.  
  17. comp.lang.c++ Frequently Asked Questions list (with answers, fortunately).
  18. Copyright (C) 1991-94 Marshall P. Cline, Ph.D.
  19. Posting 3 of 4.
  20. Posting #1 explains copying permissions, (no)warranty, table-of-contents, etc
  21.  
  22. ==============================================================================
  23. SECTION 14: Style guidelines
  24. ==============================================================================
  25.  
  26. Q74: What are some good C++ coding standards?
  27.  
  28. Thank you for reading this answer rather than just trying to set your own
  29. coding standards.
  30.  
  31. But please don't ask this question on comp.lang.c++.  Nearly every software
  32. engineer has, at some point, felt that coding standards are or can be used as a
  33. "power play."  Furthermore some attempts to set C++ coding standards have been
  34. made by those unfamiliar with the language and/or paradigm, so the standards
  35. end up being based on what WAS the state-of-the-art when the standards setters
  36. where writing code.  Such impositions generate an attitude of mistrust for
  37. coding standards.
  38.  
  39. Obviously anyone who asks this question on comp.lang.c++ wants to be trained so
  40. they DON'T run off on their own ignorance, but nonetheless the answers tend to
  41. generate more heat than light.
  42.  
  43. ==============================================================================
  44.  
  45. Q75: Are coding standards necessary?  Are they sufficient?
  46.  
  47. Coding standards do not make non OO programmers into OO programmers; only
  48. training and experience do that.  If coding standards have merit, it is that
  49. they discourage the petty fragmentation that occurs when large organizations
  50. coordinate the activities of diverse groups of programmers.
  51.  
  52. But you really want more than a coding standard.  The structure provided by
  53. coding standards gives neophytes one less degree of freedom to worry about,
  54. however pragmatics go well beyond pretty-printing standards.  Organizations
  55. need a consistent PHILOSOPHY of design and implementation.  E.g., strong or
  56. weak typing?  references or ptrs in interfaces?  stream I/O or stdio?  should
  57. C++ code call our C?  vise versa?  how should ABCs be used?  should inheritance
  58. be used as an implementation technique or as a specification technique?  what
  59. testing strategy should be employed?  inspection strategy?  should interfaces
  60. uniformly have a "get" and/or "set" method for each data member?  should
  61. interfaces be designed from the outside-in or the inside-out?  should errors be
  62. handled by try/catch/throw or return codes?  etc.
  63.  
  64. What is needed is a "pseudo standard" for detailed DESIGN.  I recommend a
  65. three-pronged approach to achieving this standardization: training, mentoring,
  66. and libraries.  Training provides "intense instruction," mentoring allows OO to
  67. be caught rather than just taught, and a high quality C++ class library
  68. provides "long term instruction."  There is a thriving commercial market for
  69. all three kinds of "training."  Advice by organizations who have been through
  70. the mill is consistent: Buy, Don't Build.  Buy libraries, buy training, buy
  71. tools, buy consulting.  Companies who have attempted to become a self-taught
  72. tool-shop as well as an application/system shop have found success difficult.
  73.  
  74. Few argue that coding standards are "ideal," or even "good," however they are
  75. necessary in the kind of organizations/situations described above.
  76.  
  77. The following FAQs provide some basic guidance in conventions and styles.
  78.  
  79. ==============================================================================
  80.  
  81. Q76: Should our organization determine coding standards from our C
  82.    experience?
  83.  
  84. No!
  85.  
  86. No matter how vast your C experience, no matter how advanced your C expertise,
  87. being a good C programmer does not make you a good C++ programmer.  Converting
  88. from C to C++ is more than just learning the syntax and semantics of the "++"
  89. part of C++.  Organizations who want the promise of OOP, but who fail to put
  90. the "OO" into OOP, are fooling themselves; the balance sheet will show their
  91. folly.
  92.  
  93. C++ coding standards should be tempered by C++ experts.  Asking comp.lang.c++
  94. is a start (but don't use the term "coding standard" in the question; instead
  95. simply say, "what are the pros and cons of this technique?").  Seek out experts
  96. who can help guide you away from pitfalls.  Get training.  Buy libraries and
  97. see if "good" libraries pass your coding standards.  Do NOT set standards by
  98. yourself unless you have considerable experience in C++.  Having no standard is
  99. better than having a bad standard, since improper "official" positions "harden"
  100. bad brain traces.  There is a thriving market for both C++ training and
  101. libraries from which to pool expertise.
  102.  
  103. One more thing: whenever something is in demand, the potential for charlatans
  104. increases.  Look before you leap.  Also ask for student-reviews from past
  105. companies, since not even expertise makes someone a good communicator.
  106. Finally, select a practitioner who can teach, not a full time teacher who has a
  107. passing knowledge of the language/paradigm.
  108.  
  109. ==============================================================================
  110.  
  111. Q77: Should I declare locals in the middle of a fn or at the top?
  112.  
  113. Declare near first use.
  114.  
  115. An object is initialized (constructed) the moment it is declared.  If you don't
  116. have enough information to initialize an object until half way down the fn, you
  117. can either initialize it to an "empty" value at the top then "assign" it later,
  118. or initialize it correctly half way down the fn.  It's cheaper (in runtime
  119. performance) to get it right the first time than to build it once, tear it
  120. down, and build it again.  Simple examples show a factor of 350% speed hit for
  121. simple classes like "String".  Your mileage may vary; surely the overall system
  122. degradation will be less that 300+%, but there WILL be degradation.
  123. UNNECESSARY degradation.
  124.  
  125. A common retort to the above is: "we"ll provide "set" methods for every datum
  126. in our objects, so the cost of construction will be spread out."  This is worse
  127. than the performance overhead, since now you're introducing a maintenance
  128. nightmare.  Providing "set" methods for every datum is tantamount to public
  129. data: you've exposed your implementation technique to the world.  The only
  130. thing you've hidden is the physical NAMES of your member objects, but the fact
  131. that you're using a List and a String and a float (for example) is open for all
  132. to see.  Maintenance generally consumes far more resources than run-time CPU.
  133.  
  134. Locals should be declared near their first use.  Sorry that this isn't familiar
  135. to C experts, but "new" doesn't necessarily mean "bad."
  136.  
  137. ==============================================================================
  138.  
  139. Q78: What source-file-name convention is best? "foo.C"? "foo.cc"? "foo.cpp"?
  140.  
  141. If you already have a convention, use it.  If not, consult your compiler to see
  142. what the compiler expects.  Typical answers are: ".C", ".cc", ".cpp", or
  143. ".cxx" (naturally the ".C" extension assumes a case-sensitive file system to
  144. distinguish ".C" from ".c").
  145.  
  146. At Paradigm Shift, Inc., we use ".C" in our Makefiles even on case-insensitive
  147. file systems (on case-insensitive file systems, we supply the compiler option
  148. that means "assume all .c files are C++ source files"; e.g., "-Tdp" for IBM
  149. CSet++, "-cpp" for Zortech C++, "-P" for Borland C++, etc).
  150.  
  151. ==============================================================================
  152.  
  153. Q79: What header-file-name convention is best? "foo.H"? "foo.hh"? "foo.hpp"?
  154.  
  155. If you already have a convention, use it.  If not, and if you don't need your
  156. editor to distinguish between C and C++ files, simply use ".h".  Otherwise use
  157. whatever the editor wants, such as ".H", ".hh", or ".hpp".
  158.  
  159. At Paradigm Shift, Inc., we use ".h" for both C and C++ source files (then
  160. again, we don't create many straight C header files).
  161.  
  162. ==============================================================================
  163.  
  164. Q80: Are there any lint-like guidelines for C++?
  165.  
  166. Yes, there are some practices which are generally considered dangerous.
  167. However none of these are universally "bad," since situations arise when
  168. even the worst of these is needed:
  169.  * a class "Fred"s assignment operator should return "*this" as an "Fred&"
  170.    (allows chaining of assignments)
  171.  * a class with any virtual fns ought to have a virtual destructor
  172.  * a class with any of {destructor, assignment operator, copy constructor}
  173.    generally needs all 3
  174.  * a class "Fred"s copy constructor and assignment operator should have "const"
  175.    in the parameter: respectively "Fred::Fred(const Fred&)" and
  176.    "Fred& Fred::operator=(const Fred&)".
  177.  * always use initialization lists for class sub-objects rather than assignment
  178.    the performance difference for user-defined classes can be substantial (3x!)
  179.  * many assignment operators should start by testing if "we" are "them"; e.g.,
  180.     Fred& Fred::operator= (const Fred& fred)
  181.     {
  182.       if (this == &fred) return *this;
  183.       //...normal assignment duties...
  184.       return *this;
  185.     }
  186.    sometimes there is no need to check, but these situations generally
  187.    correspond to when there's no need for an explicit user-specified assignment
  188.    op (as opposed to a compiler-synthesized assignment-op).
  189.  * in classes that define both "+=," "+" and "=," "a+=b" and "a=a+b" should
  190.    generally do the same thing; ditto for the other identities of builtin types
  191.    (e.g., a+=1 and ++a; p[i] and *(p+i); etc).  This can be enforced by writing
  192.    the binary ops using the "op=" forms; e.g.,
  193.     Fred operator+ (const Fred& a, const Fred& b)
  194.     {
  195.       Fred ans = a;
  196.       ans += b;
  197.       return ans;
  198.     }
  199.    This way the "constructive" binary ops don't even need to be friends.  But
  200.    it is sometimes possible to more efficiently implement common ops (e.g., if
  201.    class "Fred" is actually "String," and "+=" has to reallocate/copy string
  202.    memory, it may be better to know the eventual length from the beginning).
  203.  
  204. ==============================================================================
  205. SECTION 15: Keys for Smalltalk programmers to learn C++
  206. ==============================================================================
  207.  
  208. Q81: Why does C++'s FAQ have a section on Smalltalk? Is this
  209.    Smalltalk-bashing?
  210.  
  211. The two "major" OOPLs in the world are C++ and Smalltalk.  Due to its
  212. popularity as the OOPL with the second largest user pool, many new C++
  213. programmers come from a Smalltalk background.  This section answers the
  214. questions:
  215.  * what's different about the two languages
  216.  * what must a Smalltalk-turned-C++ programmer know to master C++
  217.  
  218. This section does *!*NOT*!* attempt to answer the questions:
  219.  * which language is "better"?
  220.  * why is Smalltalk "bad"?
  221.  * why is C++ "bad"?
  222.  
  223. Nor is it an open invitation for some Smalltalk terrorist to slash my tires
  224. while I sleep (on those rare occasions when I have time to rest these days :-).
  225.  
  226. ==============================================================================
  227.  
  228. Q82: What's the difference between C++ and Smalltalk?
  229.  
  230. The most important differences are:
  231.  
  232.  * static typing vs dynamic typing?
  233.  * must inheritance be used only for subtyping?
  234.  * value vs reference semantics?
  235.  
  236. The first two differences are illuminated in the remainder of this section; the
  237. third point is the subject of the section that follows.
  238.  
  239. If you're a Smalltalk programmer who wants to learn C++, you'd be very wise to
  240. study the next three FAQs carefully.
  241.  
  242. ==============================================================================
  243.  
  244. Q83: What is "static typing", and how is it similar/dissimilar to Smalltalk?
  245.  
  246. Static typing says the compiler checks the type-safety of every operation
  247. STATICALLY (at compile-time), rather than to generate code which will check
  248. things at run-time.  For example, with static typing, the signature matching of
  249. fn arguments is checked, and an improper match is flagged as an error by the
  250. COMPILER, not at run-time.
  251.  
  252. In OO code, the most common "typing mismatch" is invoking a member function
  253. against an object which isn't prepared to handle the operation.  E.g., if class
  254. "Fred" has member fn "f()" but not "g()", and "fred" is an instance of class
  255. "Fred", then "fred.f()" is legal and "fred.g()" is illegal.  C++ (statically
  256. typed) catches the error at compile time, and Smalltalk (dynamically typed)
  257. catches the error at run-time.  (Technically speaking, C++ is like Pascal
  258. --PSEUDO statically typed-- since ptr casts and unions can be used to violate
  259. the typing system; which reminds me: only use ptr casts and unions as often as
  260. you use "goto"s).
  261.  
  262. ==============================================================================
  263.  
  264. Q84: Which is a better fit for C++: "static typing" or "dynamic typing"?
  265.  
  266. If you want to use C++ most effectively, use it as a statically typed language.
  267.  
  268. C++ is flexible enough that you can (via ptr casts, unions, and #defines) make
  269. it "look" like Smalltalk.  But don't.  Which reminds me: try to avoid #define.
  270.  
  271. There are places where ptr casts and unions are necessary and even wholesome,
  272. but they should be used carefully and sparingly.  A ptr cast tells the compiler
  273. to believe you.  An incorrect ptr cast might corrupt your heap, scribble into
  274. memory owned by other objects, call nonexistent methods, and cause general
  275. failures.  It's not a pretty sight.  If you avoid these and related constructs,
  276. you can make your C++ code both safer and faster, since anything that can be
  277. checked at compile time is something that doesn't have to be done at run-time.
  278.  
  279. Even if you're in love with dynamic typing, please avoid it in C++, or else
  280. please consider using another language that better supports your desire to
  281. defer typing decisions to run-time.  C++ performs 100% of its type checking at
  282. compile time; it has NO built-in mechanism to do ANY type checking at run-time.
  283. If you use C++ as a dynamically typed OOPL, your life is in your own hands.
  284.  
  285. ==============================================================================
  286.  
  287. Q85: How can you tell if you have a dynamically typed C++ class library?
  288.  
  289. Hint #1: when everything is derived from a single root class, usually "Object."
  290. Hint #2: when the container classes (List, Stack, Set, etc) are non-templates.
  291. Hint #3: when the container classes (List, Stack, Set, etc) insert/extract
  292. elements as pointers to "Object" (you can put an Apple into such a container,
  293. but when you get it out, the compiler only knows that it is derived from
  294. Object, so you have to use a pointer cast to convert it back to an Apple*; and
  295. you better pray a lot that it really IS an Apple, cause your blood is on your
  296. own head).
  297.  
  298. You can make the pointer cast "safe" by using "dynamic_cast" (see earlier), but
  299. this dynamic testing is just that: dynamic.  This coding style is the essence
  300. of dynamic typing in C++.  You call a function that says "convert this Object
  301. into an Apple or give me NULL if its not an Apple," and you've got dynamic
  302. typing: you don't know what will happen until run-time.
  303.  
  304. When you use with templates to implement your containers, the C++ compiler can
  305. statically validate 99% of an application's typing information (the figure
  306. "99%" is apocryphal; some claim they always get 100%, those who need
  307. persistence get something less than 100% static type checking).  The point is:
  308. C++ gets genericity from templates, not from inheritance.
  309.  
  310. ==============================================================================
  311.  
  312. Q86: How do you use inheritance in C++, and is that different from Smalltalk?
  313.  
  314. Some people believe that the purpose of inheritance is code reuse.  In C++,
  315. this is wrong.  Stated plainly, "inheritance is not 'for' code reuse."
  316.  
  317. The purpose of inheritance in C++ is to express interface compliance
  318. (subtyping), not to get code reuse.  In C++, code reuse usually comes via
  319. composition rather than via inheritance.  In other words, inheritance is mainly
  320. a specification technique rather than an implementation technique.
  321.  
  322. This is a major difference with Smalltalk, where there is only one form of
  323. inheritance (C++ provides "private" inheritance to mean "share the code but
  324. don't conform to the interface", and "public" inheritance to mean "kind-of").
  325. The Smalltalk language proper (as opposed to coding practice) allows you to
  326. have the EFFECT of "hiding" an inherited method by providing an override that
  327. calls the "does not understand" method.  Furthermore Smalltalk allows a
  328. conceptual "is-a" relationship to exist APART from the subclassing hierarchy
  329. (subtypes don't have to be subclasses; e.g., you can make something that is-a
  330. Stack yet doesn't inherit from class Stack).
  331.  
  332. In contrast, C++ is more restrictive about inheritance: there's no way to make
  333. a "conceptual is-a" relationship without using inheritance (the C++ work-around
  334. is to separate interface from implementation via ABCs).  The C++ compiler
  335. exploits the added semantic information associated with public inheritance to
  336. provide static typing.
  337.  
  338. ==============================================================================
  339.  
  340. Q87: What are the practical consequences of diffs in Smalltalk/C++
  341.    inheritance?
  342.  
  343. Smalltalk lets you make a subtype that isn't a subclass, and allows you to make
  344. a subclass that isn't a subtype.  This allows Smalltalk programmers to be very
  345. carefree in putting data (bits, representation, data structure) into a class
  346. (e.g., you might put a linked list into a Stack class).  After all, if someone
  347. wants an array-based-Stack, they don't have to inherit from Stack; they could
  348. inherit such a class from Array if desired, even though an ArrayBasedStack is
  349. NOT a kind-of Array!
  350.  
  351. In C++, you can't be nearly as carefree.  Only mechanism (method code), but not
  352. representation (data bits) can be overridden in subclasses.  Therefore you're
  353. usually better off NOT putting the data structure in a class.  This leads to a
  354. stronger reliance on Abstract Base Classes (ABCs).
  355.  
  356. I like to think of the difference between an ATV and a Maseratti.  An ATV (all
  357. terrain vehicle) is more fun, since you can "play around" by driving through
  358. fields, streams, sidewalks, and the like.  A Maseratti, on the other hand, gets
  359. you there faster, but it forces you to stay on the road.  My advice to C++
  360. programmers is simple: stay on the road.  Even if you're one of those people
  361. who like the "expressive freedom" to drive through the bushes, don't do it in
  362. C++; it's not a good fit.
  363.  
  364. ==============================================================================
  365.  
  366. Q88: Do you need to learn a "pure" OOPL before you learn C++?
  367.  
  368. No (in fact, doing so might actually hurt you).
  369.  
  370. (Note that Smalltalk is a "pure" OOPL, and C++ is a "hybrid" OOPL).  Before
  371. reading this, please read the previous FAQs on the difference between C++ and
  372. Smalltalk.
  373.  
  374. The "purity" of the OOPL doesn't make the transition to C++ any easier.  In
  375. fact, the typical use of dynamic typing and non-subtyping inheritance can make
  376. it even harder for Smalltalk programmers to learn C++.  Paradigm Shift, Inc.,
  377. has taught OO technology to literally thousands of people, and we have noticed
  378. that people who want to learn C++ from a Smalltalk background usually have just
  379. as hard a time as those who've never seen inheritance before.  In fact, those
  380. with extensive experience with a dynamically typed OOPL (usually but not always
  381. Smalltalk) might even have a HARDER time, since it's harder to UNLEARN habits
  382. than it is to learn the statically typed way from the beginning.
  383.  
  384. ==============================================================================
  385.  
  386. Q89: What is the NIHCL?  Where can I get it?
  387.  
  388. NIHCL stands for "national-institute-of-health's-class-library."
  389. it can be acquired via anonymous ftp from [128.231.128.7]
  390. in the file pub/nihcl-3.0.tar.Z
  391.  
  392. NIHCL (some people pronounce it "N-I-H-C-L," others pronounce it like "nickel")
  393. is a C++ translation of the Smalltalk class library.  There are some ways where
  394. NIHCL's use of dynamic typing helps (e.g., persistent objects).  There are also
  395. places where its use of dynamic typing creates tension with the static typing
  396. of the C++ language.
  397.  
  398. See previous FAQs on Smalltalk for more.
  399.  
  400. ==============================================================================
  401. SECTION 16: Reference and value semantics
  402. ==============================================================================
  403.  
  404. Q90: What is value and/or reference semantics, and which is best in C++?
  405.  
  406. With reference semantics, assignment is a pointer-copy (i.e., a REFERENCE).
  407. Value (or "copy") semantics mean assignment copies the value, not just the
  408. pointer.  C++ gives you the choice: use the assignment operator to copy the
  409. value (copy/value semantics), or use a ptr-copy to copy a pointer (reference
  410. semantics).  C++ allows you to override the assignment operator to do anything
  411. your heart desires, however the default (and most common) choice is to copy the
  412. VALUE.
  413.  
  414. Pros of reference semantics: flexibility and dynamic binding (you get dynamic
  415. binding in C++ only when you pass by ptr or pass by ref, not when you pass by
  416. value).
  417.  
  418. Pros of value semantics: speed.  "Speed" seems like an odd benefit to for a
  419. feature that requires an object (vs a ptr) to be copied, but the fact of the
  420. matter is that one usually accesses an object more than one copies the object,
  421. so the cost of the occasional copies is (usually) more than offset by the
  422. benefit of having an actual object rather than a ptr to an object.
  423.  
  424. There are three cases when you have an actual object as opposed to a pointer to
  425. an object: local vars, global/static vars, and fully contained member objects
  426. in a class.  The most important of these is the last ("composition").
  427.  
  428. More info about copy-vs-reference semantics is given in the next FAQs.  Please
  429. read them all to get a balanced perspective.  The first few have intentionally
  430. been slanted toward value semantics, so if you only read the first few of the
  431. following FAQs, you'll get a warped perspective.
  432.  
  433. Assignment has other issues (e.g., shallow vs deep copy) which are not covered
  434. here.
  435.  
  436. ==============================================================================
  437.  
  438. Q91: What is "virtual data," and how-can / why-would I use it in C++?
  439.  
  440. Virtual data allows a derived class to change the exact class of a base class's
  441. member object.  Virtual data isn't strictly "supported" by C++, however it
  442. can be simulated in C++.  It ain't pretty, but it works.
  443.  
  444. To simulate virtual data in C++, the base class must have a pointer to the
  445. member object, and the derived class must provide a "new" object to be pointed
  446. to by the base class's pointer.  The base class would also have one or more
  447. normal constructors that provide their own referrent (again via "new"), and the
  448. base class's destructor would "delete" the referent.
  449.  
  450. For example, class "Stack" might have an Array member object (using a pointer),
  451. and derived class "StretchableStack" might override the base class member data
  452. from "Array" to "StretchableArray".  For this to work, StretchableArray would
  453. have to inherit from Array, so Stack would have an "Array*".  Stack's normal
  454. constructors would initialize this "Array*" with a "new Array", but Stack would
  455. also have a (possibly "protected:") constructor that would accept an "Array*"
  456. from a derived class.  StretchableArray's constructor would provide a "new
  457. StretchableArray" to this special constructor.
  458.  
  459. Pros:
  460.  * Easier implementation of StretchableStack (most of the code is inherited).
  461.  * Users can pass a StretchableStack as a kind-of Stack.
  462.  
  463. Cons:
  464.  * Adds an extra layer of indirection to access the Array.
  465.  * Adds some extra freestore allocation overhead (both new and delete).
  466.  * Adds some extra dynamic binding overhead (reason given in next FAQ).
  467.  
  468. In other words, we succeeded at making OUR job easier as the implementor of
  469. StretchableStack, but all our users pay for it.  Unfortunately the extra
  470. overhead was imposed on both users of StretchableStack AND on users of Stack.
  471.  
  472. See the FAQ after the next to find out how much the users "pay."  Also: PLEASE
  473. read the few FAQs that follow the next one too (YOU WILL NOT GET A BALANCED
  474. PERSPECTIVE WITHOUT THE OTHERS).
  475.  
  476. ==============================================================================
  477.  
  478. Q92: What's the difference between virtual data and dynamic data?
  479.  
  480. The easiest way to see the distinction is by an analogy with "virtual fns":
  481. A virtual member fn means the declaration (signature) must stay the same in
  482. subclasses, but the defn (body) can be overridden.  The overriddenness of an
  483. inherited member fn is a static property of the subclass; it doesn't change
  484. dynamically throughout the life of any particular object, nor is it possible
  485. for distinct objects of the subclass to have distinct defns of the member fn.
  486.  
  487. Now go back and re-read the previous paragraph, but make these substitutions:
  488.  * "member fn" --> "member object"
  489.  * "signature" --> "type"
  490.  * "body"      --> "exact class'
  491. After this, you'll have a working definition of virtual data.
  492.  
  493. Another way to look at this is to distinguish "per-object" member functions
  494. from "dynamic" member functions.  A "per-object" member fn is a member fn that
  495. is potentially different in any given instance of an object, and could be
  496. implemented by burying a function ptr in the object; this pointer could be
  497. "const", since the pointer will never be changed throughout the object's life.
  498. A "dynamic" member fn is a member fn that will change dynamically over time;
  499. this could also be implemented by a function ptr, but the fn ptr would not be
  500. const.
  501.  
  502. Extending the analogy, this gives us three distinct concepts for data members:
  503.  * virtual data: the defn ("class") of the member object is overridable in
  504.    subclasses provided its declaration ("type") remains the same, and this
  505.    overriddenness is a static property of the subclass.
  506.  * per-object-data: any given object of a class can instantiate a different
  507.    conformal (same type) member object upon initialization (usually a "wrapper"
  508.    object), and the exact class of the member object is a static property of
  509.    the object that wraps it.
  510.  * dynamic-data: the member object's exact class can change dynamically over
  511.    time.
  512.  
  513. The reason they all look so much the same is that none of this is "supported"
  514. in C++.  It's all merely "allowed," and in this case, the mechanism for faking
  515. each of these is the same: a ptr to a (probably abstract) base class.  In a
  516. language that made these "first class" abstraction mechanisms, the difference
  517. would be more striking, since they'd each have a different syntactic variant.
  518.  
  519. ==============================================================================
  520.  
  521. Q93: Should I normally use pointers to freestore allocated objects for my data
  522.    members, or should I use "composition"?
  523.  
  524. Composition.
  525.  
  526. Your member objects should normally be "contained" in the composite object (but
  527. not always; "wrapper" objects are a good example of where you want a ptr/ref;
  528. also the N-to-1-uses-a relationship needs something like a ptr/ref).
  529.  
  530. There are three reasons why fully contained member objects ("composition") has
  531. better performance than ptrs to freestore-allocated member objects:
  532.  
  533.  * Extra layer to indirection every time you need to access the member object.
  534.  * Extra freestore allocations ("new" in constructor, "delete" in destructor).
  535.  * Extra dynamic binding (reason given below).
  536.  
  537. ==============================================================================
  538.  
  539. Q94: What are relative costs of the 3 performance hits associated with
  540.    allocating member objects from the freestore?
  541.  
  542. The three performance hits are enumerated in the previous FAQ:
  543.  * By itself, an extra layer of indirection is small potatoes.
  544.  * Freestore allocations can be a performance issue (the performance of the
  545.    typical implementation of malloc degrades when there are many allocations;
  546.    OO s/w can easily become "freestore bound" unless you're careful).
  547.  * The extra dynamic binding comes from having a ptr rather than an object.
  548.    Whenever the C++ compiler can know an object's EXACT class, virtual fn
  549.    calls can be STATICALLY bound, which allows inlining.  Inlining allows
  550.    zillions (would you believe half a dozen :-) optimization opportunities
  551.    such as procedural integration, register lifetime issues, etc.  The C++
  552.    compiler can know an object's exact class in three circumstances: local
  553.    variables, global/static variables, and fully-contained member objects.
  554.  
  555. Thus fully-contained member objects allow significant optimizations that
  556. wouldn't be possible under the "member objects-by-ptr" approach.  This is the
  557. main reason that languages which enforce reference-semantics have "inherent"
  558. performance challenges.
  559.  
  560. NOTE: PLEASE READ THE NEXT THREE FAQs TO GET A BALANCED PERSPECTIVE!
  561.  
  562. ==============================================================================
  563.  
  564. Q95: Are "inline virtual" member fns ever actually "inlined"?
  565.  
  566. Yes but...
  567.  
  568. A virtual call via a ptr or ref is always resolved dynamically, which can never
  569. be inlined.  Reason: the compiler can't know which actual code to call until
  570. run-time (i.e., dynamically), since the code may be from a derived class that
  571. was created after the caller was compiled.
  572.  
  573. Therefore the only time an inline virtual call can be inlined is when the
  574. compiler knows the "exact class" of the object which is the target of the
  575. virtual function call.  This can only happen when the compiler has an actual
  576. object rather than a pointer or reference to an object.  I.e., either with a
  577. local object, a global/static object, or a fully contained object inside a
  578. composite.
  579.  
  580. Note that the difference between inlining and non-inlining is normally MUCH
  581. more significant than the difference between a regular fn call and a virtual fn
  582. call.  For example, the difference between a regular fn call and a virtual fn
  583. call is often just two extra memory references, but the difference between an
  584. inline function and a non-inline function can be as much as an order of
  585. magnitude (for zillions of calls to insignificant member fns, loss of inlining
  586. virtual fns can result in 25X speed degradation!  [Doug Lea, "Customization in
  587. C++," proc Usenix C++ 1990]).
  588.  
  589. A practical consequence of this insight: don't get bogged down in the endless
  590. debates (or sales tactics!) of compiler/language vendors who compare the cost
  591. of a virtual function call on their language/compiler with the same on another
  592. language/compiler.  Such comparisons are largely meaningless when compared with
  593. the ability of the language/compiler to "inline expand" member function calls.
  594. I.e., many language implementation vendors make a big stink about how good
  595. their dispatch strategy is, but if these implementations don't INLINE method
  596. calls, the overall system performance would be poor, since it is inlining --NOT
  597. dispatching-- that has the greatest performance impact.
  598.  
  599. NOTE: PLEASE READ THE NEXT TWO FAQs TO SEE THE OTHER SIDE OF THIS COIN!
  600.  
  601. ==============================================================================
  602.  
  603. Q96: Sounds like I should never use reference semantics, right?
  604.  
  605. Wrong.
  606.  
  607. Reference semantics are A Good Thing.  We can't live without pointers.  We just
  608. don't want our s/w to be One Gigantic Rats Nest Of Pointers.  In C++, you can
  609. pick and choose where you want reference semantics (ptrs/refs) and where you'd
  610. like value semantics (where objects physically contain other objects etc).  In
  611. a large system, there should be a balance.  However if you implement absolutely
  612. EVERYTHING as a pointer, you'll get enormous speed hits.
  613.  
  614. Objects near the problem skin are larger than higher level objects.  The
  615. IDENTITY of these "problem space" abstractions is usually more important than
  616. their "value."  Thus reference semantics should be used for problem-space
  617. objects.
  618.  
  619. Note that these problem space objects are normally at a higher level of
  620. abstraction than the solution space objects, so the problem space objects
  621. normally have a relatively lower frequency of interaction.  Therefore C++ gives
  622. us an IDEAL situation: we choose reference semantics for objects that need
  623. unique identity or that are too large to copy, and we can choose value
  624. semantics for the others.  Thus the highest frequency objects will end up with
  625. value semantics, since we install flexibility only where it doesn't hurt us,
  626. and we install performance where we need it most!
  627.  
  628. These are some of the many issues the come into play with real OO design.
  629. OO/C++ mastery takes time and high quality training.  If you want a powerful
  630. tool, you've got to invest.
  631.  
  632.            <<<<DON'T STOP NOW!  READ THE NEXT FAQ TOO!!>>>>
  633.  
  634. ==============================================================================
  635.  
  636. Q97: Does the poor performance of ref semantics mean I should pass-by-value?
  637.  
  638. Nope.
  639.  
  640. The previous FAQ were talking about MEMBER OBJECTS, not parameters.  Generally,
  641. objects that are part of an inheritance hierarchy should be passed by ref or by
  642. ptr, NOT by value, since only then do you get the (desired) dynamic binding
  643. (pass-by-value doesn't mix with inheritance, since larger subclass objects get
  644. "sliced" when passed by value as a base class object).
  645.  
  646. Unless compelling reasons are given to the contrary, member objects should be
  647. by value and parameters should be by reference.  The discussion in the previous
  648. few FAQs indicates some of the "compelling reasons" for when member objects
  649. should be by reference.
  650.  
  651. --
  652. Marshall Cline
  653. --
  654. Marshall P. Cline, Ph.D. / Paradigm Shift Inc / PO Box 5108 / Potsdam NY 13676
  655. cline@sun.soe.clarkson.edu / 315-353-6100 / FAX: 315-353-6110
  656.